package org.happen.android.core.net;

import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.message.AbstractHttpMessage;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.happen.android.app.AppContext;
import org.happen.android.app.ILife;
import org.happen.android.bean.BaseRequest;
import org.happen.android.bean.BaseResponse;
import org.happen.android.bean.IResponseError;
import org.happen.android.bean.entity.KeyValue;
import org.happen.android.bean.request.PostRequest;
import org.happen.android.bean.request.UploadRequest;
import org.happen.android.bean.response.DownLoadResponse;
import org.happen.android.bean.response.FailResponse;
import org.liushui.mycommons.android.log.McLog;
import org.liushui.mycommons.android.net.McUtilNet;
import org.liushui.mycommons.android.thread.ThreadWorker;

import android.os.Handler;
import android.os.Message;

public class AppRequestManager implements ILife
{

	private static AppRequestManager instance = new AppRequestManager();

	public static AppRequestManager getInstance()
	{
		return instance;
	}

	static AppContext appContext; // 全局上下文
	Handler handler; // handler对象，负责线程通信

	// private IProcess processProxy;// 网络处理代理

	private AppRequestManager()
	{
		appContext = AppContext.getInstance();
		handler = new ResponseHandler();
	}

	public void init()
	{
		McLog.m(this, "init");
		// processProxy = new ProcessProxy(appContext);
	}

	public void doGet(BaseRequest request, OnRequestCallback callback)
	{
		this.execute(new SimpleRequestRunnable(request, callback));
	}

	public void doPost(PostRequest request, OnRequestCallback callback)
	{
		this.execute(new PostRequestRunnable(request, callback));
	}

	public void doUpload(UploadRequest request, OnRequestCallback callback)
	{
		this.execute(new UploadRequestRunnable(request, callback));
	}

	public void doDownload(BaseRequest request, OnRequestCallback callback)
	{
		this.execute(new DownloadRequestRunnable(request, callback));
	}

	void execute(SimpleRequestRunnable runnable)
	{
		McLog.m(this, "execute");
		ThreadWorker.execute(runnable);
	}

	public void unInit()
	{
		McLog.m(this, "unInit");
	}

	class SimpleRequestRunnable implements Runnable
	{
		BaseRequest request;
		OnRequestCallback callback;

		public SimpleRequestRunnable(BaseRequest r, OnRequestCallback c)
		{
			request = r;
			callback = c;
		}

		public void run()
		{
			McLog.m(this, "run");
			Message msg = handler.obtainMessage();
			TempResponse temp = new TempResponse();
			temp.callback = callback;
			temp.req = request;
			String reqId = request.reqId;
			boolean isConnnect = McUtilNet.isConnectInternet();// 判读网络是否连接
			McLog.i("Is Connect Internet:" + isConnnect);
			if (isConnnect)
			{
				McLog.i("ThreadName:" + Thread.currentThread().getName());
				McLog.i("---------------------------------request----------------------------------");
				McLog.i(request);
				McLog.i("---------------------------------------------------------------------------");
				BaseResponse resp = exec();// processProxy.process(request);// 代理处理
				McLog.i("----------------------------------response---------------------------------");
				resp.respId = reqId;
				McLog.i(resp);
				McLog.i("---------------------------------------------------------------------------");
				temp.resp = resp;
			} else
			{
				temp.resp = FailResponse.NET_EX;
			}
			McLog.i(temp.resp);
			// 交给ui线程请求的结果
			msg.obj = temp;
			msg.sendToTarget();
		}

		protected BaseResponse exec()
		{
			BaseResponse resp = null;
			try
			{
				resp = new BaseResponse();
				HttpClient httpclient = AppHttpClient.getInstance().createClient();

				String url = ReqRespUtils.makeGetUrl(request);
				McLog.i("request url : " + url);

				HttpGet httpGet = new HttpGet(url);
				addClientHead(httpGet);
				HttpResponse httpResponse = httpclient.execute(httpGet);

				int code = httpResponse.getStatusLine().getStatusCode();
				McLog.i("http status code:" + code);
				if (code == HttpStatus.SC_OK)
				{
					String result = EntityUtils.toString(httpResponse.getEntity(), HTTP.UTF_8);
					McLog.i("result = " + result);
					resp.json = result;
				} else
				{
					throw new Exception();
				}
			} catch (Exception e)
			{
				McLog.e("Exception", e);
				resp = new FailResponse(e);
			}
			return resp;
		}

		protected void addClientHead(AbstractHttpMessage httpMethod)
		{
			httpMethod.addHeader("User-Agent", "android");
		}
	}

	class UploadRequestRunnable extends SimpleRequestRunnable
	{

		public UploadRequestRunnable(BaseRequest r, OnRequestCallback c)
		{
			super(r, c);
		}

		protected BaseResponse exec()
		{
			BaseResponse resp = null;
			try
			{
				resp = new BaseResponse();
				UploadRequest uploadRequest = (UploadRequest) request;
				HttpClient httpclient = AppHttpClient.getInstance().createClient();

				String url = ReqRespUtils.makeGetUrl(request);
				McLog.i("request url : " + url);

				MultipartEntity me = new MultipartEntity();
				me.addPart(uploadRequest.paramName, new InputStreamBody(uploadRequest.inputStream, uploadRequest.fileName));

				HttpPost httpPost = new HttpPost(url);
				httpPost.setEntity(me);
				addClientHead(httpPost);

				HttpResponse httpResponse = httpclient.execute(httpPost);

				int code = httpResponse.getStatusLine().getStatusCode();
				McLog.i("http status code:" + code);
				if (code == HttpStatus.SC_OK)
				{
					String result = EntityUtils.toString(httpResponse.getEntity(), HTTP.UTF_8);
					McLog.i("result = " + result);
					resp.json = result;
				} else
				{
					throw new Exception();
				}
			} catch (Exception e)
			{
				McLog.e("Exception", e);
				resp = new FailResponse(e);
			}
			return resp;
		}
	}

	class PostRequestRunnable extends SimpleRequestRunnable
	{

		public PostRequestRunnable(BaseRequest r, OnRequestCallback c)
		{
			super(r, c);
		}

		protected BaseResponse exec()
		{
			BaseResponse resp = null;
			try
			{
				resp = new BaseResponse();
				PostRequest postRequest = (PostRequest) request;
				HttpClient httpclient = AppHttpClient.getInstance().createClient();

				String url = ReqRespUtils.makeGetUrl(request);
				McLog.i("request url : " + url);

				MultipartEntity me = new MultipartEntity();
				List<KeyValue> list = postRequest.getPostParams();
				if (list != null)
				{
					for (KeyValue kv : list)
					{
						me.addPart(kv.key, new StringBody(kv.value));
					}
				}

				HttpPost httpPost = new HttpPost(url);
				httpPost.setEntity(me);
				addClientHead(httpPost);

				HttpResponse httpResponse = httpclient.execute(httpPost);

				int code = httpResponse.getStatusLine().getStatusCode();
				McLog.i("http status code:" + code);
				if (code == HttpStatus.SC_OK)
				{
					String result = EntityUtils.toString(httpResponse.getEntity(), HTTP.UTF_8);
					McLog.i("result = " + result);
					resp.json = result;
				} else
				{
					throw new Exception();
				}
			} catch (Exception e)
			{
				McLog.e("Exception", e);
				resp = new FailResponse(e);
			}
			return resp;
		}
	}

	class DownloadRequestRunnable extends SimpleRequestRunnable
	{

		public DownloadRequestRunnable(BaseRequest r, OnRequestCallback c)
		{
			super(r, c);
		}

		protected BaseResponse exec()
		{
			BaseResponse resp = null;
			try
			{
				HttpClient httpclient = AppHttpClient.getInstance().createClient();

				String url = ReqRespUtils.makeGetUrl(request);
				McLog.i("request url : " + url);

				HttpGet httpGet = new HttpGet(url);
				addClientHead(httpGet);

				HttpResponse httpResponse = httpclient.execute(httpGet);
				int code = httpResponse.getStatusLine().getStatusCode();
				DownLoadResponse response = new DownLoadResponse();
				McLog.i("http status code:" + code);
				if (code == HttpStatus.SC_OK)
				{
					response.inputStream = httpResponse.getEntity().getContent();
				} else
				{
					throw new Exception();
				}
				resp = response;
			} catch (Exception e)
			{
				McLog.e("Exception", e);
				resp = new FailResponse(e);
			}
			return resp;
		}
	}

	static class ResponseHandler extends Handler
	{
		public void handleMessage(Message msg)
		{
			McLog.md(getClass(), "handleMessage");
			TempResponse temp = (TempResponse) msg.obj;
			temp.doCallback();
		}
	}

	static class TempResponse
	{
		BaseRequest req;
		BaseResponse resp;
		OnRequestCallback callback;

		void doCallback()
		{
			if (callback != null)
			{
				if (resp instanceof IResponseError)
				{
					FailResponse fr = (FailResponse) resp;
					callback.onException(fr.exception);
				} else
				{
					callback.onSuccess(req, resp);
				}
			}
		}
	}
}